package com.wjw.java.others.innerClass_;

/**
 * 匿名内部类：定义在外部类的局部位置,比如方法中或代码块
 * 本质是类(拥有类的成员)、内部类、该类没有名称、同时还是一个对象
 * -------------------------------------------------------------
 * new 类或接口(参数列表){
 *  //类体
 * }
 * -------------------------------------------------------------
 * 细节：
 * 1.定义在外部类的局部位置,通常在方法里或代码块中
 * 2.匿名内部类访问外部类的成员,直接访问即可,包括private的
 * 3.不能添加访问修饰符
 * 4.作用域仅仅在定义它的方法中或代码块中
 * 5.外部其他类不能访问局部内部类(因为局部内部类的地位是一个局部变量)
 * 6.如果外部类和匿名内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用
 *   外部类名.this.成员
 * -------------------------------------------------------------
 */
//外部其他类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        //1.传统的方式：接口 + 接口的实现类
        System.out.println("============1.传统的方式：接口 + 接口的实现类============");
        UserService userService = new UserServiceImpl();
        userService.cry();
        System.out.println("============2.基于接口的匿名内部类：============");
        //2.基于接口的匿名内部类：为了简化传统方式的代码
        Outer2 outer2 = new Outer2();
        outer2.outerMethod1();
        //3.基于类的匿名内部类
        System.out.println("============3.基于类的匿名内部类============");
        outer2.outerMethod2();
        //4.基于类的匿名内部类,简写
        System.out.println("============4.基于类的匿名内部类,简写============");
        outer2.outerMethod3();
    }
}
//接口UserService
interface UserService{
    public void cry();
}
//接口的实现类UserServiceImpl
class UserServiceImpl implements UserService{
    @Override
    public void cry() {
        System.out.println("1.接口的实现类,重写接口的cry()方法");
    }
}
//外部类Outer2
class Outer2{
    private String msg = "你好啊";
    public void outerMethod1(){
        /**
         * 2.基于接口的匿名内部类：相当于new一个UserService接口实现类,然后用一个变量接收
         * 编译类型为=左边UserService,运行类型为=右边,也就是这个匿名内部类Outer2$1
         * 基于接口的匿名内部类底层:
         *
         * class XXX implements UserService{
         *    @Override
         *    public void cry() {
         *      System.out.println("2.接口的匿名内部类,重写接口的cry()方法");
         *    }
         * }
         *
         * 这里的XXX就是匿名内部类的名称：等于外部类$1 ==> Outer2$1
         */
        UserService us = new UserService() {
            private String msg = "你好啊222";
            @Override
            public void cry() {
                System.out.println("msg:"+msg);//就近原则：你好啊222
                //Outer2.this本质上就是外部类的对象,即哪个类调用了outerMethod1(),Outer2.this就是哪个对象
                System.out.println("msg:"+Outer2.this.msg);//你好啊
                System.out.println("2.接口的匿名内部类,重写接口的cry()方法");
            }
        };
        us.cry();
        //class com.wjw.java.others.innerClass_.Outer2$1
        System.out.println("匿名内部类的运行类型："+us.getClass());
    }

    public void outerMethod2(){
        /**
         * 基于类的匿名内部类：相当于new一个Father类的子类,然后用一个变量接收
         * 编译类型为=左边Father,运行类型为=右边,也就是这个匿名内部类Outer2$2
         * 基于类的匿名内部类底层:
         * class XXX extends Father{
         *    @Override
         *    public void fatherTest() {
         *       System.out.println("baba...");
         *    }
         *
         *  这里的XXX就是匿名内部类的名称：等于外部类$2 ==> Outer2$2
         * }
         */
        Father father = new Father("王爸爸"){
            @Override
            public void fatherTest() {
                System.out.println("baba...");
            }
        };
        father.fatherTest();
        //class com.wjw.java.others.innerClass_.Outer2$2
        System.out.println("匿名内部类的运行类型："+father.getClass());
    }

    public void outerMethod3(){
        //基于类的匿名内部类,简写
        new Father("李爸爸"){
            @Override
            public void fatherTest() {
                System.out.println("今天天气真好,爸爸");
            }

            @Override
            public void say(String words) {
                System.out.println("李焕英:"+words);
            }
        }.say("你好啊");
    }
}
//外部类Father
class Father{
    public Father(String name) {
        System.out.println("name:"+name);
    }
    public void fatherTest(){
        System.out.println("爸爸");
    }
    public void say(String words){
        System.out.println("words:"+words);
    }
}